import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate, Trend } from 'k6/metrics';

// 自定义指标
const uploadSuccessRate = new Rate('upload_success');
const uploadDuration = new Trend('upload_duration');

// 测试配置
export const options = {
  stages: [
    { duration: '10s', target: 100 }, // 10秒内增加到1000并发
    { duration: '30s', target: 100 }, // 保持1000并发30秒
    { duration: '10s', target: 0 },     // 10秒内降为0
  ],
  thresholds: {
    http_req_duration: ['p(95)<2000'], // 95%的请求在2秒内完成
    upload_success: ['rate>0.95'],      // 成功率大于95%
  },
};

// 测试配置参数（可通过环境变量覆盖）
const BASE_URL = __ENV.BASE_URL || 'http://192.168.0.105:80';
const USERNAME = __ENV.USERNAME || 'tjc';
const PASSWORD = __ENV.PASSWORD || '123456';
const FILE_SIZE = parseInt(__ENV.FILE_SIZE || '1024'); // 1KB
const TOTAL_SIZE_MB = parseInt(__ENV.TOTAL_SIZE_MB || '10'); // 10MB
const PARENT_ID = parseInt(__ENV.PARENT_ID || '0'); // 父目录ID，默认0（根目录）

// 计算需要上传的文件数量
const TOTAL_FILES = (TOTAL_SIZE_MB * 1024 * 1024) / FILE_SIZE; // 10MB / 1KB = 10240

// 生成1KB的测试文件内容
function generateTestFile(size) {
  const content = 'x'.repeat(size);
  return content;
}

// 从 URL 提取 hostname（用于设置 Cookie domain）
function extractHostname(url) {
  try {
    const urlObj = new URL(url);
    return urlObj.hostname;
  } catch (e) {
    // 如果 URL 解析失败，尝试手动提取
    const match = url.match(/^https?:\/\/([^\/:]+)/);
    return match ? match[1] : '';
  }
}

// URL 解码函数（处理 Cookie 中的 URL 编码值）
function urlDecode(value) {
  try {
    return decodeURIComponent(value);
  } catch (e) {
    return value;
  }
}

// 登录并获取token
function login() {
  const loginUrl = `${BASE_URL}/api/v1/login`;
  const payload = JSON.stringify({
    username: USERNAME,
    password: PASSWORD,
  });
  
  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
  };
  
  const response = http.post(loginUrl, payload, params);
  
  const success = check(response, {
    'login status is 200': (r) => r.status === 200,
    'login response has access_token': (r) => {
      try {
        const body = JSON.parse(r.body);
        return body.access_token !== undefined;
      } catch (e) {
        return false;
      }
    },
  });
  
  if (!success) {
    console.error('Login failed:', response.status, response.body);
    return null;
  }
  
  const body = JSON.parse(response.body);
  
  // 从响应中获取 token 和 csrf_token
  const accessToken = body.access_token;
  const csrfToken = body.csrf_token || '';
  
  // 从 Cookie 中获取（如果服务器设置了）
  const cookies = response.cookies || {};
  let tokenFromCookie = null;
  let csrfFromCookie = null;
  
  if (cookies.token && cookies.token.length > 0) {
    tokenFromCookie = cookies.token[0].value;
  }
  if (cookies.csrf_token && cookies.csrf_token.length > 0) {
    // Cookie 中的 csrf_token 可能是 URL 编码的，需要解码
    csrfFromCookie = urlDecode(cookies.csrf_token[0].value);
  }
  
  // 使用响应中的 token 或 Cookie 中的 token
  const finalToken = accessToken || tokenFromCookie;
  // CSRF token 优先使用响应中的（未编码），否则使用 Cookie 中的（已解码）
  const finalCsrfToken = csrfToken || csrfFromCookie || '';
  
  // 提取 hostname 用于设置 Cookie domain
  const hostname = extractHostname(BASE_URL);
  
  // 确保 cookies 对象存在并包含 token（参考前端逻辑）
  // 如果服务器已经设置了 Cookie，使用服务器的值；否则手动设置
  if (finalToken) {
    if (!cookies.token || cookies.token.length === 0 || !cookies.token[0].value) {
      if (!cookies.token) {
        cookies.token = [];
      }
      cookies.token.push({
        name: 'token',
        value: finalToken,
        domain: hostname || undefined, // 如果 hostname 为空，不设置 domain（让浏览器使用默认）
        path: '/',
        secure: false,
        httpOnly: true,
        maxAge: 3600,
      });
    } else {
      // 更新现有 Cookie 的 domain（如果为空）
      if (!cookies.token[0].domain && hostname) {
        cookies.token[0].domain = hostname;
      }
    }
  }
  
  if (finalCsrfToken) {
    if (!cookies.csrf_token || cookies.csrf_token.length === 0 || !cookies.csrf_token[0].value) {
      if (!cookies.csrf_token) {
        cookies.csrf_token = [];
      }
      cookies.csrf_token.push({
        name: 'csrf_token',
        value: finalCsrfToken,
        domain: hostname || undefined,
        path: '/',
        secure: false,
        httpOnly: false,
        maxAge: 86400,
      });
    } else {
      // 更新现有 Cookie 的 domain（如果为空）并确保值是解码后的
      if (!cookies.csrf_token[0].domain && hostname) {
        cookies.csrf_token[0].domain = hostname;
      }
      // 确保值是解码后的（用于后续请求）
      cookies.csrf_token[0].value = finalCsrfToken;
    }
  }
  
  console.log('Login successful:', {
    hasToken: !!finalToken,
    hasCsrfToken: !!finalCsrfToken,
    cookieToken: cookies.token && cookies.token.length > 0 && cookies.token[0].value ? 'present' : 'missing',
    cookieCsrf: cookies.csrf_token && cookies.csrf_token.length > 0 && cookies.csrf_token[0].value ? 'present' : 'missing',
    hostname: hostname,
  });
  
  return {
    accessToken: finalToken,
    csrfToken: finalCsrfToken,
    cookies: cookies,
  };
}

// 构建 Cookie header 字符串
// 注意：在 k6 中，setup 返回的数据会被序列化，cookies 对象结构可能变化
// 所以优先使用直接传递的 token 值
function buildCookieHeader(accessToken, csrfToken, cookies) {
  const cookieStrings = [];
  
  // 优先使用直接传递的 token（避免序列化问题）
  if (accessToken) {
    cookieStrings.push(`token=${accessToken}`);
  } else if (cookies) {
    // 备用方案：从 cookies 对象中提取
    if (cookies.token) {
      const tokenCookie = Array.isArray(cookies.token) ? cookies.token[0] : cookies.token;
      if (tokenCookie && tokenCookie.value) {
        cookieStrings.push(`token=${tokenCookie.value}`);
      }
    }
  }
  
  if (csrfToken) {
    cookieStrings.push(`csrf_token=${csrfToken}`);
  } else if (cookies) {
    // 备用方案：从 cookies 对象中提取
    if (cookies.csrf_token) {
      const csrfCookie = Array.isArray(cookies.csrf_token) ? cookies.csrf_token[0] : cookies.csrf_token;
      if (csrfCookie && csrfCookie.value) {
        cookieStrings.push(`csrf_token=${csrfCookie.value}`);
      }
    }
  }
  
  return cookieStrings.length > 0 ? cookieStrings.join('; ') : null;
}

// 初始化上传任务（参考前端 initUpload 方法）
function initUpload(accessToken, csrfToken, cookies, fileName, fileSize, mimeType) {
  const initUrl = `${BASE_URL}/api/v1/file/InitUpload`;
  const payload = JSON.stringify({
    file_name: fileName,
    file_size: fileSize,
    mime_type: mimeType,
    parent_id: PARENT_ID, // 参考前端，传递 parent_id
  });
  
  const headers = {
    'Content-Type': 'application/json',
  };
  
  // 添加 CSRF token（参考前端逻辑）
  if (csrfToken) {
    headers['X-CSRF-Token'] = csrfToken;
  }
  
  // 构建 Cookie header（使用直接传递的 token，避免序列化问题）
  const cookieHeader = buildCookieHeader(accessToken, csrfToken, cookies);
  if (cookieHeader) {
    headers['Cookie'] = cookieHeader;
  }
  
  const params = {
    headers: headers,
    cookies: cookies, // k6 会自动管理 Cookie，但我们也手动设置 header 确保传递
  };
  
  const response = http.post(initUrl, payload, params);
  
  const success = check(response, {
    'init upload status is 200': (r) => r.status === 200,
    'init upload returns upload_id': (r) => {
      try {
        const body = JSON.parse(r.body);
        return body.upload_id !== undefined || body.id !== undefined;
      } catch (e) {
        return false;
      }
    },
  });
  
  if (!success) {
    console.error(`InitUpload failed: status=${response.status}, body=${response.body.substring(0, 200)}`);
    console.error(`  Cookies sent: ${headers['Cookie'] || 'none'}`);
    console.error(`  CSRF Token: ${csrfToken || 'none'}`);
    return null;
  }
  
  const body = JSON.parse(response.body);
  const uploadId = body.upload_id || body.id;
  const chunkSize = body.chunk_size || (2 * 1024 * 1024); // 默认2MB
  
  return { uploadId, chunkSize };
}

// 上传分片（参考前端 uploadChunks 方法）
function uploadChunk(accessToken, csrfToken, cookies, uploadId, chunkIndex, chunkContent, chunkSize) {
  const uploadUrl = `${BASE_URL}/api/v1/file/UploadChunk`;
  
  // 构建 multipart/form-data 请求（参考前端 FormData）
  const formData = {
    file: http.file(chunkContent, `chunk_${chunkIndex}.bin`, 'application/octet-stream'),
    upload_id: uploadId.toString(),
    chunk_index: chunkIndex.toString(),
    size: chunkSize.toString(),
  };
  
  // 将 CSRF token 添加到 FormData（参考前端逻辑）
  if (csrfToken) {
    formData.csrf_token = csrfToken;
  }
  
  const headers = {};
  
  // 添加 CSRF token 到 header（参考前端）
  if (csrfToken) {
    headers['X-CSRF-Token'] = csrfToken;
  }
  
  // 添加 size 到 header（参考前端）
  headers['size'] = chunkSize.toString();
  
  // 构建 Cookie header（使用直接传递的 token，避免序列化问题）
  const cookieHeader = buildCookieHeader(accessToken, csrfToken, cookies);
  if (cookieHeader) {
    headers['Cookie'] = cookieHeader;
  }
  
  const params = {
    headers: headers,
    cookies: cookies, // k6 会自动管理 Cookie，但我们也手动设置 header 确保传递
  };
  
  const response = http.post(uploadUrl, formData, params);
  
  const success = check(response, {
    'upload chunk status is 200': (r) => r.status === 200,
  });
  
  if (!success) {
    console.error(`UploadChunk failed: status=${response.status}, body=${response.body.substring(0, 200)}`);
  }
  
  return success;
}

// 完成上传（参考前端 completeUpload 方法）
function completeUpload(accessToken, csrfToken, cookies, uploadId, hash = '') {
  // 参考前端：使用 query 参数传递 parent_id 和 hash
  const completeUrl = `${BASE_URL}/api/v1/file/CompleteUpload/${uploadId}?parent_id=${PARENT_ID}${hash ? `&hash=${encodeURIComponent(hash)}` : ''}`;
  
  const headers = {
    'Content-Type': 'application/json',
  };
  
  // 添加 CSRF token（参考前端）
  if (csrfToken) {
    headers['X-CSRF-Token'] = csrfToken;
  }
  
  // 构建 Cookie header（使用直接传递的 token，避免序列化问题）
  const cookieHeader = buildCookieHeader(accessToken, csrfToken, cookies);
  if (cookieHeader) {
    headers['Cookie'] = cookieHeader;
  }
  
  const params = {
    headers: headers,
    cookies: cookies, // k6 会自动管理 Cookie，但我们也手动设置 header 确保传递
  };
  
  const response = http.post(completeUrl, '{}', params);
  
  const success = check(response, {
    'complete upload status is 200': (r) => r.status === 200,
  });
  
  if (!success) {
    console.error(`CompleteUpload failed: status=${response.status}, body=${response.body.substring(0, 200)}`);
  }
  
  return success;
}

// 完整的上传流程（参考前端 uploadFile 方法）
function uploadFile(accessToken, csrfToken, cookies, fileContent, fileName, fileSize) {
  const startTime = Date.now();
  
  // 1. 初始化上传任务
  const initResult = initUpload(accessToken, csrfToken, cookies, fileName, fileSize, 'application/octet-stream');
  if (!initResult || !initResult.uploadId) {
    uploadSuccessRate.add(false);
    return false;
  }
  
  const { uploadId, chunkSize } = initResult;
  
  // 2. 上传分片（1KB文件可能只需要一个分片）
  const totalChunks = Math.ceil(fileSize / chunkSize);
  let allChunksSuccess = true;
  
  for (let i = 0; i < totalChunks; i++) {
    const start = i * chunkSize;
    const end = Math.min(start + chunkSize, fileSize);
    const chunkContent = fileContent.substring(start, end);
    const actualChunkSize = end - start;
    
    const chunkSuccess = uploadChunk(accessToken, csrfToken, cookies, uploadId, i, chunkContent, actualChunkSize);
    if (!chunkSuccess) {
      allChunksSuccess = false;
      break;
    }
  }
  
  if (!allChunksSuccess) {
    uploadSuccessRate.add(false);
    return false;
  }
  
  // 3. 完成上传（不传递 hash，让后端计算）
  const completeSuccess = completeUpload(accessToken, csrfToken, cookies, uploadId, '');
  
  const duration = Date.now() - startTime;
  uploadSuccessRate.add(completeSuccess);
  uploadDuration.add(duration);
  
  if (!completeSuccess) {
    console.error(`Upload failed for file: ${fileName}`);
  }
  
  return completeSuccess;
}

// 初始化阶段：登录获取token
export function setup() {
  console.log('Setting up test...');
  console.log(`Base URL: ${BASE_URL}`);
  console.log(`Username: ${USERNAME}`);
  console.log(`File size: ${FILE_SIZE} bytes (${FILE_SIZE / 1024} KB)`);
  console.log(`Total size: ${TOTAL_SIZE_MB} MB`);
  console.log(`Total files: ${TOTAL_FILES}`);
  console.log(`Parent ID: ${PARENT_ID}`);
  
  const tokens = login();
  if (!tokens) {
    console.error('Failed to login during setup. Please check credentials.');
    return null;
  }
  
  console.log('Login successful, token obtained');
  return tokens;
}

// 主测试函数
export default function (data) {
  if (!data || !data.accessToken) {
    console.error('No token available, skipping test');
    return;
  }
  
  // 生成唯一的文件名
  const fileName = `test_${__VU}_${__ITER}_${Date.now()}.bin`;
  const fileContent = generateTestFile(FILE_SIZE);
  
  // 使用分片上传接口上传文件（参考前端逻辑）
  const success = uploadFile(
    data.accessToken,
    data.csrfToken,
    data.cookies,
    fileContent,
    fileName,
    FILE_SIZE
  );
  
  if (!success) {
    console.error(`Upload failed for file: ${fileName}`);
  }
  
  // 短暂休眠，避免过于频繁的请求
  sleep(0.1);
}

// 测试完成后的清理
export function teardown(data) {
  console.log('Test completed');
  if (data) {
    console.log('Token was used for testing');
  }
}
